﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Thinker.SignChannel.Entities;
using Thinker.SignChannel.Repositories;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.ObjectMapping;
using Volo.Abp.Uow;

namespace Thinker.SignChannel.People;

public class PersonManager(IPersonRepository personRepository, IObjectMapper objectMapper)
    : ITransientDependency
{
    public async Task<Person> CreateAsync(PersonInfo info)
    {
        var person = objectMapper.Map<PersonInfo, Person>(info);
        return await personRepository.InsertAsync(person, true);
    }

    public async Task<Person> UpdateAsync(Guid id, PersonInfo info)
    {
        var person = await personRepository.GetAsync(id);
        objectMapper.Map(info, person);
        return await personRepository.UpdateAsync(person, true);
    }

    public Task DeleteAsync(Guid id)
    {
        return personRepository.DeleteAsync(id);
    }

    public async Task<int> DeleteAllAsync()
    {
        var total = await personRepository.CountAsync();
        await personRepository.DeleteAsync(x => true);
        return total;
    }

    private async Task<(Person Person, bool IsNew)> CreateOrUpdateAsync(PersonInfo info)
    {
        var person = await personRepository.FindByIdNumberAsync(info.IdNumber);
        if (person != null)
        {
            objectMapper.Map(info, person);
            return (person, false);
        }

        person = objectMapper.Map<PersonInfo, Person>(info);
        return (person, true);
    }

    [UnitOfWork]
    public async Task<List<Person>> AddOrChangeAllAsync(IEnumerable<PersonInfo> infos)
    {
        var created = new List<Person>();
        var updated = new List<Person>();
        foreach (var info in infos)
        {
            var (person, isNew) = await CreateOrUpdateAsync(info);
            if (isNew)
            {
                created.Add(person);
            }
            else
            {
                updated.Add(person);
            }
        }

        await personRepository.InsertManyAsync(created, true);
        await personRepository.UpdateManyAsync(updated, true);
        return created.Concat(updated).ToList();
    }
}